package com.netty.pro.netty.simple;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.util.CharsetUtil;

import java.util.concurrent.TimeUnit;

/**
 * @author xuzn
 * @ClassName: NettyServerHandler
 * @ProjectName netty-pro
 * @Description: 自定义一个handler, 需要继承netty规定好的某一个HandlerAdapter
 * @date 2020/3/10/14:37
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
  // 读取实际数据(读取客户端发送过来的消息)

  /**
   * ChannelHandlerContext:上下文对象,含有通道pipeline,管道channel和地址
   * msg:客户端发送的数据,默认是object
   *
   * @param ctx
   * @param msg
   * @throws Exception
   */
  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    System.out.println("服务器的读取线程:" + Thread.currentThread().getName());
    System.out.println("server ctx=" + ctx);
    System.out.println("channel和channelPipeline的关系:");
    Channel channel = ctx.channel();
    // pipeline是一个双向链表
    ChannelPipeline pipeline = ctx.pipeline();

    // 将消息msg转成buffer
    // ByteBuf是由netty提供,不是Nio的ByteBuffer,ByteBuf的性能更高
    ByteBuf buf = (ByteBuf) msg;
    System.out.println("客户端发送的消息是:" + buf.toString(CharsetUtil.UTF_8));
    System.out.println("客户端地址:" + ctx.channel().remoteAddress());
    Thread.sleep(5 * 1000);
    ctx.writeAndFlush(Unpooled.copiedBuffer("hello client,(๑ŐдŐ)b2", CharsetUtil.UTF_8));
    long start = System.currentTimeMillis();
    ctx.channel().eventLoop().execute(new Runnable() {
      @Override
      public void run() {
        try {
          Thread.sleep(5 * 1000);
          ctx.writeAndFlush(Unpooled.copiedBuffer("hello client,(๑ŐдŐ)b2", CharsetUtil.UTF_8));
          long end1 = System.currentTimeMillis();
          long hao1 = end1 - start;
          System.out.println("睡眠5秒耗时:" + hao1);
        } catch (Exception e) {
          e.printStackTrace();
        }

      }
    });

    ctx.channel().eventLoop().execute(new Runnable() {
      @Override
      public void run() {
        try {
          Thread.sleep(5 * 1000);
          ctx.writeAndFlush(Unpooled.copiedBuffer("hello client,(๑ŐдŐ)b3", CharsetUtil.UTF_8));
          long end2 = System.currentTimeMillis();
          long hao2 = end2 - start;
          System.out.println("睡眠5秒耗时:" + hao2);
        } catch (Exception e) {
          e.printStackTrace();
        }

      }
    });

    ctx.channel().eventLoop().schedule(new Runnable() {
      @Override
      public void run() {
        try {
          Thread.sleep(5 * 1000);
          ctx.writeAndFlush(Unpooled.copiedBuffer("hello client,(๑ŐдŐ)b4", CharsetUtil.UTF_8));
          long end2 = System.currentTimeMillis();
          long hao2 = end2 - start;
          System.out.println("scheduleTaskQueue睡眠5秒耗时:" + hao2);
        } catch (Exception e) {
          e.printStackTrace();
        }

      }
    }, 5, TimeUnit.SECONDS);
    System.out.println("go on~~~");
  }

  // 数据读取完毕
  @Override
  public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    // 将数据写入到缓存并发送
    // 一般来讲先将数据进行编码
    ctx.writeAndFlush(Unpooled.copiedBuffer("hello client,(๑ŐдŐ)b1", CharsetUtil.UTF_8));
  }

  // 处理异常一般情况下关闭通道
  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    ctx.close();
  }
}
